In recent years, the mobile computing marketplace has been flooded with smaller and faster personal devices. These next generation handhelds, cell phones, automotive telematics and personal information devices sport high resolution screens in excess of 320 by 240 pixels, processors faster than 300 MHz, and more than 16 Mbyte of dynamic RAM. New cell phones already in the marketplace combine traditional cellular technology with the power of a small personal computer. Future devices will create brand new breeds of handheld personal computers with unparalleled power, mobility, and battery life.
Despite these impending revolutions in device capability, the market has failed to produce common, underlying standards for mobile interfaces. Even in this nascent stage of device adoption, it is clear to industry observers that the wireless application market has become fragmented. JAVA-based technologies such as J2ME have been stymied with high hurdles to application qualification and numerous manufacturer-specific additions. MICROSOFT.NET technology, while promising, has been slow to grow on non-Intel platforms. Binary-based solutions like SYMBIANOS and BREW have failed to develop traction in a cautious market. Competing standards and interests in the industry among carriers, device manufactures, technology vendors, operating system vendors and application developer continue to plague the industry.
Several significant hurdles obstruct easy development of rich, widely deployable applications that run (at least partially) natively on a device:
Multiple platforms require porting code to a variety of different API standards. Even within a single architecture specification, different platforms have slight variations that require extensive testing and modification.
Competing languages (primarily C and JAVA) have no easy porting relationship.
Service operators have created qualification hurdles that require expensive certification tests for applications before they can be deployed on a given platform.
The industry has yet to agree on a common distribution mechanism for applications. Consequently, getting the application onto multiple devices becomes extremely difficult.
Various sets of interests must be satisfied before these devices will realize their widespread potential as business and consumer platforms: For example, end users seek a rich, easy-to-use interface and a cost effective and easy way to acquire and run mobile applications. Furthermore, they seek a user interface that is common across applications. Users want some reasonable assurances about the quality and integrity of the applications they receive. They are also interested in making greater use of the power and flexibility of the new devices.
Carriers, mobile operators, media companies and other entities seeking to provide and distribute applications must choose a means to encourage application developers while maintaining their own revenue streams. Also carriers maintain a high concern about the security of code running on the devices connected to their networks
Developers (whether independent or employed by software companies) need platforms that are economically viable to develop upon, non-complicated and connected to distribution points or mechanisms capable of disseminating applications widely. Many developers are small software shops that cannot afford to develop on multiple platforms and seek multiple certifications from operators.
It would therefore be desirable to provide methods and structures that would address these concerns.
In this regard, it is worth noting that most computers in common use are based around the general computing model established by John Von Neumann in 1945. In this model, programs are written in the form of ordered lists of instructions and stored within the main memory of a computing system. Variations on this design since 1945 have led to the architecture of modern INTEL, POWERPC and other microprocessor-based systems. Even the JAVA platform by SUN MICROSYSTEMS, which uses a virtual machine that runs on host platforms, uses a variation on the Von Neumann architecture.
One implication of the Van Neumann machine is an opcode-based program execution model, in which instructions are written for the native processing language of the platform (or a virtual processing language in the case of JAVA). These instructions consist of programming opcodes that have varying degree of granularity. In some cases they can be as simple as very basic mathematics and memory loading and saving. In other cases, they are more advanced, where individual opcodes for object manipulation, memory allocation and I/O systems.
In this traditional execution model, a processor reads instructions from a memory location, decodes the instructions found there and performs some work, which may involve additional reading and writing of memory data. When the instruction is complete, and succeeding instruction is read, either the next instruction in sequence or an instruction at the beginning of a new sequence. In this way, complicated program behavior can be established through creation of algorithms, loops, conditional statements, etc. Those familiar with the arts of computer design are aware that modern implementations use extremely complex optimizations and heuristics to achieve greater performance in this basic model, including Intel's Superscalar architecture.
To ease the development of programming instructions for a computer application, programs called compilers translate a program from a high-level representation available in structured text, XML or some other human-significant format to the lower level machine language of the underlying hardware (or emulation of hardware.) In this case, a programming language with certain grammatical rules is established, and programs are written to conform to this specification. Examples of compiled languages include C, C++, JAVA, Fortran, and Cobol.
In the traditional execution model, programs wishing to access resources outside of their memory space must use a set of conventions supported by an operating system. These conventions allow each program that runs on a computer to access resources in a consistent and protectable manner. Such a convention may be regarded as an Application Programmer Interface (or API.) Typically, the API calls are triggered either by joining a program with libraries from the operating system at link-time or at run-time, or through the low-level triggering of interrupts, processor exceptions, or special memory regions that contain significance to the host operating system. Over time, these conventions have become quite extensive, where the typical operating system (such as WINDOWS 2000) contains tens of thousands of application programmer interface hooks, accessible either by shared library or through compile-time insertion of code. These APIs are typically an arbitrary organization of computer and operating system functionality and contain special rules. For instance, setWindowTitle( ) in WINDOWS cannot be called before a newWindowQ call has been made. The programmer is responsible for being consistent both to the rules of the language as well as the rules of the API.
In some cases, programs written at a high level are not compiled down into their machine-language equivalent. Instead, a native computer program written in machine-language acts as a emulating processor, reading an internal representation of a current instruction, executing it and then following its own rules for the selection of a subsequent instruction. These interpreted programming languages offer the benefit of greater flexibility for the language designer, easier implementation of a new programming language, usually at the expense of some efficiency since the a level of translation is always in place between the hardware processor and the internal instruction processor. Examples include PERL, versions of Basic, UNIX shell languages, PYTHON, etc.
Typical computer applications organize their information within their memory space using arbitrary data structures, which divide that space into meaningful chunks of data that can be referenced implicitly by the loading and saving operations of the processor. To the computer and to the operating system, these data structures are entirely private, and only the continuing flow of instructions through the processor gives these organizations any meaning. If a program wishes to save its context and state to resume execution later, it must conform to one of two constraints.
It must marshal up all of its relevant data and innermost state pertinent to the resumption of the program in a meaningful way, into a private or publicly structured serial bundle of data and save that data to a persistent location. When the program must resume, it must obtain information to resurrect its internal data structures in their previous state by decomposing the bundle of data it previously wrote. Variations on this model include placing data into a database, serial memory ring or other external structure. This strategy has the advantage that the state of the program could be resumed on a different platform or computer system than the original, however the application must take excessive care to ensure that every piece of data has been saved in an identifiable format.
It must save its existing buffer of memory, exactly as it was left, into a single large snapshot, disentangle any memory references maintained by the operating system and write the complete state of the processor to disk. A variation on this method is used by MICROSOFT's operating system in its hibernation mode, and by the old BSD tool “undump.” This method requires very little work to decompose and marshal private data structure into a secondary form, however it contains a very stringent limitation: The application “image” can only be restored on a system that implements the same hardware and operating system state that the original program had run on. Any differences could cause unpredictable problems with the executable.
These complexities express themselves in the equally complex strategies computer programmers have used to construct computer programs that run on multiple systems simultaneously. For example, when a small, embedded device needs to perform some complex processing operation on a more powerful server, it must build a complete description of the work required, and then transmit it to the remote server. This involves yet another API between the small device and the remote device (e.g., SOAP, and the like).
Thus, the Von Neumann model and the program execution models that result from it, while useful and ubiquitous, present limitations that computer scientists and engineers have recognized but failed to address. Some of these limitations include:
Instruction Based Programming: Applications written for instantiations of the Von Neumann architecture must write their applications in the native (or emulated) code set of the given platform. Consequently, the ability for optimization after the code has been compiled lies within local heuristics usually available only to the instruction processor. Furthermore, the instructions must be processed linearly, which encourages a procedural style of programming where program code is largely instructive instead of descriptive.
Seeding Complex Data Structures: Applications that work with and manipulate complex nested data structures must populate those structures with either long lists of instructions (such as the list of instructions used to populate a user interface) or the loading of those data structures from some other source. Vast medications to data structures after they have been initialized requires algorithms to be created within the program to manage the manipulations of the data. These algorithms can be complex and rely on an instructive model whereby the changes are made linearly step-by-step.
Remote Execution: Remote execution involves either migrating images of a running program to a second location, or through the explicit marshalling and unmarshalling of relevant computing data
State Saving: Programs that are halted and wish to save their state for resumption at a later time must use one of the two difficult strategies listed above, each with potential drawbacks.
Private Application Structures: Applications store all of their data using implicit data structures within their memory core. Consequently, applications that wish to share data with each other or with the host operating system must perform a translation into some common format (such as published data structures, or XML, or whatever.)
API Issues: Each operating system and software component must provide an application programmer interface to bridge data and activities between the program and resources available to the computer, including the user interface. Thus, it would be desirable to provide methods and structures that overcome these limitations as well.